﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

namespace Nirvana
{
    [RequireComponent(typeof(Text))]
    [AddComponentMenu("Nirvana/UI/Language/Text I18N")]
    [DisallowMultipleComponent]
    [ExecuteInEditMode]
    public sealed class TextI18N : Translatable
    {
        //不换行空格
        private readonly string no_breaking_space = "\u00A0";
        [Serializable]
        private struct BindLanguageText
        {
            [Tooltip("The languaget type.")]
            public I18NLanguageType languagetype;
            [Tooltip("The translate text.")]
            public string translate;
        };

        /// <summary>
        /// 换行处理
        /// </summary>
        [Serializable]
        private struct BindLanguageTextNewline
        {
            [Tooltip("The languaget type.")]
            public I18NLanguageType languagetype;

            [Tooltip("The text is New Line.")]
            public bool isNewline;

            [Tooltip("this length of the text for one line")]
            public int length;
        };

        /// <summary>
        /// BestFit缩放处理
        /// </summary>
        [Serializable]
        private struct BindLanguageTextBestFit
        {
            [Tooltip("The languaget type.")]
            public I18NLanguageType languagetype;

            [Tooltip("Toggle BestFit for the Text.")]
            public bool isBestFit;
        };


        [Tooltip("The font for i18n support.")]
        [SerializeField]
        private I18NFont i18nfont;

        /// <summary>
        /// 内置翻译表，不通过keyid获取，直接设置
        /// </summary>
        [SerializeField]
        [Tooltip("The bind Language Text list.")]
        private List<BindLanguageText> binds = new List<BindLanguageText>();

        [SerializeField]
        [Tooltip("The bind Language Text NewLine.")]
        private List<BindLanguageTextNewline> bindNewlines = new List<BindLanguageTextNewline>();

        [SerializeField]
        [Tooltip("The bind Language Text BestFit.")]
        private List<BindLanguageTextBestFit> bindBestFits = new List<BindLanguageTextBestFit>();
        

        Text m_txt;
        public I18NFont I18NFont
        {
            get { return i18nfont; }
            set { i18nfont = value; }
        }

        //#if UNITY_EDITOR
        //        [InitializeOnLoadMethod]
        //        private static void Init()
        //        {
        //            PrefabUtility.prefabInstanceUpdated += InitPrefab;
        //        }
        //        private static void InitPrefab(GameObject prefab)
        //        {
        //            GameObject gameObject = PrefabUtility.GetCorrespondingObjectFromSource(prefab) as GameObject;
        //            if (gameObject == null)
        //            {
        //                return;
        //            }
        //            TextI18N[] txtI18Ns = gameObject.GetComponentsInChildren<TextI18N>();
        //            foreach (var p in txtI18Ns)
        //            {
        //                if (p.i18nfont != null)
        //                {
        //                    Text txt = p.GetComponent<Text>();
        //                    txt.font = p.i18nfont.FindFont(I18N.Language);
        //                    EditorUtility.SetDirty(txt);
        //                }
        //            }
        //        }
        //#endif

        protected override void Awake()
        {
            base.Awake();
            m_txt = this.GetComponent<Text>();
            //if (m_txt != null) m_txt.RegisterDirtyVerticesCallback(OnTextChange);
        }

        private void OnDestroy()
        {
            //if (m_txt != null)
            //{
            //    m_txt.UnregisterDirtyVerticesCallback(OnTextChange);
            //}
        }

        private void OnTextChange()
        {
            if (m_txt != null && m_txt.text.Contains(" "))
            {
                m_txt.text = m_txt.text.Replace(" ", no_breaking_space);
            }
        }

        protected override void TranslateText()
        {
            if (m_txt == null)
            {
                m_txt = this.GetComponent<Text>();
                if (m_txt == null) return;
            }
            if (this.i18nfont == null)
            {
                this.UpdateText(m_txt);
                return;
            }
            I18NLanguageType language = I18N.Language;
            Font font = this.i18nfont.FindFont(language);
            if (font == null)
            {
                Debug.LogErrorFormat("The text {0} can not find font for language: {1}", base.name, language);
                m_txt.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
                return;
            }
            m_txt.font = font;
            this.UpdateText(m_txt);
        }

        public override void GetTranslate(out string txt)
        {
            txt = string.Empty;
            if (!string.IsNullOrEmpty(KeyId))
            {
                base.GetTranslate(out txt);
            }
            else
            {
                I18NLanguageType language = I18N.Language;
                foreach (var f in binds)
                {
                    if (f.languagetype == language)
                    {
                        txt = f.translate;
                        return;
                    }
                }
            }

        }

        private void UpdateText(Text txt)
        {
            if (Application.isPlaying)
            {

                string msg;
                GetTranslate(out msg);
                
                if (!string.IsNullOrEmpty(msg) && msg != txt.text)
                {
                    txt.text = msg;
                    txt.text = txt.text.Replace("\\n", "\n");
                    NewlineFilter(txt,msg);
                    BestFitFilter(txt);
                }
                    
            }
            else
            {

#if UNITY_EDITOR
                string msg;
                GetTranslate(out msg);
                if (!string.IsNullOrEmpty(msg) && msg != txt.text)
                {
                    txt.text = msg;
                    txt.text = txt.text.Replace("\\n", "\n");
                    NewlineFilter(txt,msg);
                    BestFitFilter(txt);
                    EditorUtility.SetDirty(txt);
                }
#endif
            }

        }


        private void NewlineFilter(Text txt,string msg)
        {

            I18NLanguageType language = I18N.Language;
            foreach (var f in bindNewlines)
            {

                if (f.languagetype == language && f.isNewline && f.length > 0)
                {
                    int charNumber = f.length;
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < msg.Length; i += charNumber)//首先判断字符串的长度，循环截取，进去循环后首先判断字符串是否大于每段的长度
                    {
                        if ((msg.Length - i) > charNumber)//如果是，就截取
                        {
                            sb.AppendLine(msg.Substring(i, charNumber));
                        }
                        else
                        {
                            sb.Append(msg.Substring(i));//如果不是，就截取最后剩下的那部分
                        }
                    }
                    txt.text = sb.ToString();
                    return;
                }
            }

        }

        private void BestFitFilter(Text txt)
        {
            I18NLanguageType language = I18N.Language;
            foreach (var f in bindBestFits)
            {

                if (f.languagetype == language && f.isBestFit)
                {
                    txt.resizeTextForBestFit = f.isBestFit;
                    return;
                } 
                else
                    txt.resizeTextForBestFit = false;
            }
            
        }

    }
}

